import IShape from "../interfaces/IShape";
import Vector2 from "../maths/Vector2";
import ITransformable from "../interfaces/ITransformable";
import IRenderState from "../interfaces/IRenderState";
import Matrix2D from "../maths/Matrix2D";
import ERenderType from "../enums/ERenderType";

// 在class之前使用abstract关键字表示当前类为抽象类
export default abstract class BaseShape2D implements IShape {
    // 2D 局部坐标的绘制
    public axisXStyle: string | CanvasGradient | CanvasPattern;
    public axisYStyle: string | CanvasGradient | CanvasPattern;
    public axisLineWidth: number;
    public axisLength: number;
    // 接口成员属性实现
    public data: any;
    // 在属性前使用abstract关键字表示一个抽象属性
    // 子类必须override，返回当前子类的实际类型字符串
    public abstract get type(): string;
    // 在方法前面使用abstract关键字表示一个抽象方法
    // IHittable接口方法，子类必须覆写本方法
    public abstract hitTest(localPt: Vector2, transform: ITransformable): boolean;

    public constructor() {
        this.axisXStyle = 'rgba(255, 0, 0, 128)';
        this.axisYStyle = 'rgba(0, 255, 0, 128)';
        this.axisLineWidth = 1;
        this.axisLength = 100;
        this.data = undefined;
    }

    // 用于绘制坐标系x轴和y轴，以利于debug显示
    protected drawLine(ctx: CanvasRenderingContext2D, style: string | CanvasGradient | CanvasPattern, isAxisX: boolean = true): void {
        ctx.save();
        ctx.strokeStyle = style;
        ctx.lineWidth = this.axisLineWidth;
        ctx.beginPath();
        ctx.moveTo(0, 0);
        if (isAxisX) {
            ctx.lineTo(this.axisLength, 0);
        } else {
            ctx.lineTo(0, this.axisLength);
        }
        ctx.stroke();
        ctx.restore();
    }

    public beginDraw(transformable: ITransformable, state: IRenderState, context: CanvasRenderingContext2D): void {
        // 渲染状态入堆栈
        context.save();
        // 设置渲染状态
        context.lineWidth = state.lineWidth;
        context.strokeStyle = state.strokeStyle;
        context.fillStyle = state.fillStyle;
        // 通过ITransformable接口获得当前IShape的全局矩阵
        // 然后设置变换矩阵
        let mat: Matrix2D = transformable.getWorldMatrix();
        context.setTransform(mat.values[0], mat.values[1], mat.values[2], mat.values[3], mat.values[4], mat.values[5]);
    }

    // 子类必须覆写（override）draw方法，如有需要（大部分情况下），则调用基类方法  (super . draw ( ) )
    // 具体绘制过程在draw中实现，基类实现调用fill、stroke、STROKE_FILL和clip命令
    public draw(transformable: ITransformable, state: IRenderState, context: CanvasRenderingContext2D, ): void {
        //调用绘制命令
        if (state.renderType === ERenderType.STROKE) {
            context.stroke();
        } else if (state.renderType === ERenderType.FILL) {
            context.fill();
        } else if (state.renderType === ERenderType.STROKE_FILL) {
            context.stroke();
            context.fill();
        } else if (state.renderType === ERenderType.CLIP) {
            context.clip();
        }
    }

    public endDraw(transformable: ITransformable, state: IRenderState, context: CanvasRenderingContext2D): void {
        // 非裁剪状态下，并且showCoordSystem为true的情况下，绘制出坐标系
        if (state.renderType !== ERenderType.CLIP) {
            if (state.showCoordSystem) {
                this.drawLine(context, this.axisXStyle, true);
                this.drawLine(context, this.axisYStyle, false);
            }
            // 渲染状态出栈
            context.restore();
        }
    }
}